package soundManager 
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.media.SoundMixer;
	import flash.media.SoundTransform;
	import flash.utils.Dictionary;
	
	
	/**
	 * 
	 * ...
	 * @author SChabanov
	 */
	public final class SoundManager
	{
		
			
		/**
		 * base library storage for SoundItems
		 */
		private static var _soundLibrary:Dictionary = new Dictionary(true);
		
		/**
		 * global setter
		 * buffertime for all
		 */
		public static function set globalBuffer(value:Number):void
		{
			SoundMixer.bufferTime = value;
		}
		/**
		 * mute/unmute by soundType from data in library
		 * disable/enable volume
		 * @param	type
		 */
		public static function mute(type:uint,value:Boolean):void
		{
			for (var name:String in _soundLibrary) 
			{
				var s:SoundItem = _soundLibrary[name];
				if (s.soundType == type)s.mute = value;
			}
		}
				
		/**
		* global stops all sounds
		*/
		public static function stopAll(global:Boolean=false):void
		{
			if (global)
			{
				SoundMixer.stopAll();
			}else {
				for (var name:String in _soundLibrary) 
				{
					if(_soundLibrary[name].isPlaying)_soundLibrary[name].stop();
				}
			}
		
		}
		/**
		 * stops sound raised by playSound();
		 * @param	soundId
		 */
		public static function stopSound(soundId:String):void
		{
			var sitem:SoundItem = _soundLibrary[soundId];
			if(sitem)sitem.stop();
		}
		
		
		
		/**
		 * global volume changer
		 * @param	volume
		 */
		public static function changeVolume(volume:Number,global:Boolean=false):void
		{
			if (global)
			{
				var current:SoundTransform = SoundMixer.soundTransform;
				current.volume = volume;
				SoundMixer.soundTransform = current;
			}else {
				for (var name:String in _soundLibrary) 
				{
					var s:SoundItem = _soundLibrary[name];
					s.volume = volume;
				}
			}
			
			
		}
		/**
		 * global changer
		 * @param	value value -1,0,1 
		 */
		public static function changeBalance(value:Number,global:Boolean=false):void
		{
			if (global)
			{
				var current:SoundTransform = SoundMixer.soundTransform;
				current.pan = value;
				SoundMixer.soundTransform = current;
			}
			
		}
		
		/**
		 * 
		 * @param	soundId
		 * @param	soundComplete callback
		 */
		public static function playSound(soundId:String,soundComplete:Function=null):void
		{		
			var sitem:SoundItem = _soundLibrary[soundId];
			if (sitem)
			{
				if (!sitem.isLoaded) sitem.addEventListener(IOErrorEvent.IO_ERROR, onIoErrorHandler, false, 0, true);
				if (soundComplete != null) 
				{
					if(!sitem.hasEventListener(Event.SOUND_COMPLETE))sitem.addEventListener(Event.SOUND_COMPLETE, soundComplete);
				}
				sitem.play();
			}
		}
		/**
		 * for many times call sound
		 * 
		 * @param	soundId
		 * @param	stramComplete
		 * @param	position
		 * @param	volume
		 * @param	balance
		 */
		public static function playStreamSound(soundId:String,streamComplete:Function=null,position:Number=0,volume:Number=1,balance:Number = 0):void
		{
			var sitem:SoundItem = _soundLibrary[soundId];
			if (sitem)
			{
				if(!sitem.isLoaded)sitem.addEventListener(IOErrorEvent.IO_ERROR, onIoErrorHandler, false, 0, true);
				if (streamComplete != null) {
					sitem.addEventListener(SoundItem.STREAM_COMPLETE, streamComplete);
				}
				sitem.playStream(position, volume, balance);
			}
		}
		/**
		 * remove not loaded assets
		 * @param	e
		 */
		static private function onIoErrorHandler(e:IOErrorEvent):void 
		{
			var sitem:SoundItem = e.currentTarget as SoundItem;
			sitem.removeEventListener(IOErrorEvent.IO_ERROR, onIoErrorHandler);
			Logger.globalLog("Sound '"+ sitem.soundId+ "' not loaded "+ e.text,true);
			removeSound(sitem.soundId);
			
		}
		
		/**
		 * base method for add to library
		 * for wraper can use SoundModel
		 * 
		 * @param	soundId
		 * @param	source
		 * @param	position
		 * @param	loops
		 * @param	volume
		 * @param	soundType
		 * @param	bufferTime
		 * @param	checkPolicy
		 * @return
		 */
		public static function addSoundItem(soundId:String, source:Object,position:Number=0,loops:int = 0,volume:Number = 1,soundType:uint = 0,bufferTime:Number = 1000, checkPolicy:Boolean = false):Boolean
		{
			if (_soundLibrary[soundId] != null) return false;
			var s:SoundItem = new SoundItem(source, soundId, bufferTime, checkPolicy);
			//s.addEventListener(SoundItem.DESTROYED, onItemDestroyed, false, 0, true);
			s.soundType = soundType;
			s.initPlayParams(position, loops, volume);
			_soundLibrary[soundId] = s;
			return true;
		}
		
		/**
		 * 
		 */
		public static function removeAllSounds():void
		{
			for (var name:String in _soundLibrary) 
			{
				_soundLibrary[name].destroy();
			}
			_soundLibrary = null;
			_soundLibrary = new Dictionary(true);
		}
		/**
		 * 
		 * @param	soundId
		 */
		public static function removeSound(soundId:String):void
		{
			var sitem:SoundItem = _soundLibrary[soundId];
			if (sitem)sitem.destroy();
			delete _soundLibrary[soundId];
			Logger.globalLog("SoundManager: '" + soundId + "' removed");
		}
		
		/**
		 * 
		 * @param	soundId
		 * @return ISoundItem for manual control
		 */
		public static function getSoundItem(soundId:String):ISoundItem
		{
			return _soundLibrary[soundId];
		}
			
		
	/*	static private function onItemDestroyed(e:Event):void 
		{
			
		}*/
		
	}

}